import { FileWithPreview } from '@/shared/interfaces';
import { CheckEmailResponseDto, PasswordCheckDto, TokenDTO } from '@/shared/interfaces/generated';
import { createReducer, PayloadAction } from '@reduxjs/toolkit';

import {
  authByEmail,
  changeAuthType,
  checkEmailExist,
  checkPassword,
  clearAuthByEmailStatus,
  clearAuthType,
  clearEmailAuthError,
  clearEmailStatus,
  clearError,
  clearFeedbackFiles,
  clearPasswordCorrectStatus,
  refreshTokenPair,
  registrationByEmail,
  sendFeedbackMessage,
  setAuthEmail,
  setCheckAuth,
  setCurrentEmail,
  setEmailAuthProcess,
  setFeedbackFiles,
  setInAuth,
  signInSocial,
  signOut,
  toggleGoToFeedback,
} from './actions';

interface StateTypes {
  isAuth: boolean | null | undefined;
  loading: boolean;
  refreshToken: null | string;
  accessToken: null | string;
  userId: number | null;
  expires: null | number;
  error: null | string;
  emailAuthProcess: string;
  phoneAuth: {
    loading: boolean;
    success: null | string;
  };
  phoneAuthCheckCode: {
    loading: boolean;
    error: null | string;
    success: boolean;
  };
  emailRegistration: {
    loading: boolean;
    error: null | string;
    success: boolean;
  };
  emailAuth: {
    loading: boolean;
    error: null | string;
    success: boolean;
  };
  feedbackFiles: FileWithPreview[];
  sendingFeedback: {
    success: boolean;
    error: null | string;
    loading: boolean;
  };
  doesUserExist: boolean | null;
  currentEmail: string;
  authEmail: string;
  isChangedAuthType: null | boolean;
  isAuthByPhone: boolean;
  isCorrectPassword: null | boolean;
  goToFeedback: boolean;
}

const initialState: StateTypes = {
  isAuth: undefined,
  sendingFeedback: {
    success: false,
    error: null,
    loading: false,
  },
  userId: null,
  loading: false,
  feedbackFiles: [],
  error: null,
  emailAuthProcess: '',
  refreshToken: typeof localStorage !== 'undefined' ? localStorage.getItem('refreshToken') : null,
  accessToken: typeof localStorage !== 'undefined' ? localStorage.getItem('accessToken') : null,
  expires: null,
  phoneAuth: {
    loading: false,
    success: null,
  },
  phoneAuthCheckCode: {
    loading: false,
    error: null,
    success: false,
  },
  emailRegistration: {
    loading: false,
    error: null,
    success: false,
  },
  emailAuth: {
    loading: false,
    error: null,
    success: false,
  },
  doesUserExist: null,
  currentEmail: '',
  authEmail: '',
  isChangedAuthType: null,
  isAuthByPhone: false,
  isCorrectPassword: null,
  goToFeedback: false,
};

export const authReducer = createReducer(initialState, (builder) => {
  builder
    // Вход через социальную сеть
    .addCase(signInSocial.pending.type, (state) => {
      state.error = null;
      state.loading = false;
    })

    .addCase(setEmailAuthProcess, (state, action: PayloadAction<string>) => {
      const { payload } = action;
      state.emailAuthProcess = payload.trim();
    })

    .addCase(setCheckAuth, (state, action: PayloadAction<{ userId: number; email?: string; expiresIn: number }>) => {
      const { userId, email, expiresIn } = action.payload;
      state.isAuth = true;
      state.expires = expiresIn;
      state.userId = userId;
      if (email) {
        state.authEmail = email;
      }
    })

    .addCase(setInAuth, (state) => {
      state.isAuth = false;
      state.accessToken = null;
      state.refreshToken = null;
      state.expires = null;
    })

    .addCase(signInSocial.fulfilled.type, (state, action: PayloadAction<TokenDTO>) => {
      state.expires = action.payload.expiresIn;
      state.refreshToken = action.payload.refreshToken;
      state.accessToken = action.payload.accessToken;
      state.isAuth = true;
    })
    .addCase(signInSocial.rejected.type, (state, action: PayloadAction<string>) => {
      state.isAuth = false;
      state.error = action.payload;
    })

    // Обновление пары токенов
    .addCase(refreshTokenPair.fulfilled.type, (state, action: PayloadAction<TokenDTO>) => {
      state.error = null;
      state.expires = action.payload.expiresIn;
      state.refreshToken = action.payload.refreshToken;
      state.accessToken = action.payload.accessToken;
    })
    .addCase(refreshTokenPair.rejected.type, (state, action: PayloadAction<string>) => {
      state.error = action.payload;
      state.isAuth = false;
      state.expires = null;
      state.refreshToken = null;
      state.accessToken = null;
    })

    // Разлогин при удалении профиля
    .addCase(signOut.fulfilled.type, (state) => {
      state.isAuth = false;
      state.loading = false;
      state.error = null;
      state.refreshToken = null;
      state.accessToken = null;
      state.expires = null;
      state.phoneAuth.loading = false;
      state.phoneAuth.success = null;
      state.isChangedAuthType = null;
      state.isAuthByPhone = false;
      state.authEmail = '';
      state.emailRegistration.success = false;
    })

    // Установить статус проверки регистрации по почте
    .addCase(checkEmailExist.fulfilled.type, (state, action: PayloadAction<CheckEmailResponseDto>) => {
      state.doesUserExist = action.payload.doesUserExist;
    })

    // Сброс статуса проверки регистрации по почте
    .addCase(clearEmailStatus, (state) => {
      state.doesUserExist = null;
    })

    .addCase(clearEmailAuthError, (state) => {
      state.emailAuth.error = null;
    })

    // установка файлов
    .addCase(setFeedbackFiles, (state, action) => {
      state.feedbackFiles = [...state.feedbackFiles, ...action.payload];
    })

    // очистка файлов
    .addCase(clearFeedbackFiles, (state) => {
      state.feedbackFiles = [];
    })

    // Отправляем сообщение обратной связи
    .addCase(sendFeedbackMessage.pending.type, (state) => {
      state.sendingFeedback.loading = true;
      state.sendingFeedback.error = null;
    })
    .addCase(sendFeedbackMessage.fulfilled.type, (state) => {
      state.sendingFeedback.success = true;
      state.sendingFeedback.loading = false;
    })
    .addCase(sendFeedbackMessage.rejected.type, (state, action: PayloadAction<string>) => {
      state.sendingFeedback.error = action.payload;
    })
    // Установить почту, с которой будет проводиться авторизация или регистрация
    .addCase(setCurrentEmail, (state, action: PayloadAction<string>) => {
      state.currentEmail = action.payload;
    })

    // Установить почту, с которой проводилась текущая авторизация
    .addCase(setAuthEmail.fulfilled.type, (state, action: PayloadAction<string>) => {
      state.authEmail = action.payload;
    })

    // Регистрация по почте
    .addCase(registrationByEmail.pending.type, (state) => {
      state.emailRegistration.loading = true;
      state.emailRegistration.error = null;
    })

    .addCase(registrationByEmail.fulfilled.type, (state, action: PayloadAction<TokenDTO>) => {
      state.accessToken = action.payload.accessToken;
      state.refreshToken = action.payload.refreshToken;
      state.expires = action.payload.expiresIn;
      state.emailRegistration.loading = false;
      state.emailRegistration.success = true;
    })

    .addCase(registrationByEmail.rejected.type, (state, action: PayloadAction<string>) => {
      state.isAuth = false;
      state.emailRegistration.error = action.payload;
      state.emailRegistration.loading = false;
    })

    // Авторизация по почте
    .addCase(authByEmail.pending.type, (state) => {
      state.emailAuth.loading = true;
      state.emailAuth.error = null;
    })

    .addCase(authByEmail.fulfilled.type, (state, action: PayloadAction<TokenDTO>) => {
      state.accessToken = action.payload.accessToken;
      state.refreshToken = action.payload.refreshToken;
      state.expires = action.payload.expiresIn;
      state.emailAuth.loading = false;
      state.emailAuth.success = true;
    })

    .addCase(authByEmail.rejected.type, (state, action: PayloadAction<string>) => {
      state.isAuth = false;
      state.emailAuth.error = action.payload;
      state.emailAuth.loading = false;
    })

    // Cбросить статус ошибки/успеха авторизации по почте
    .addCase(clearAuthByEmailStatus, (state) => {
      state.emailAuth.error = null;
      state.emailAuth.success = false;
    })

    // Сбросить ошибку при авторизации
    .addCase(clearError, (state) => {
      state.error = null;
    })

    // Установить статус редиректа на Feedback
    .addCase(toggleGoToFeedback, (state) => {
      state.goToFeedback = !state.goToFeedback;
    })

    // Установить статус изменения типа авторизации на авторизацию по почте и паролю
    .addCase(changeAuthType.fulfilled.type, (state) => {
      state.isChangedAuthType = true;
      state.isAuthByPhone = false;
    })

    .addCase(changeAuthType.rejected.type, (state) => {
      state.isChangedAuthType = false;
    })

    // Сбросить статус изменения типа авторизации
    .addCase(clearAuthType, (state) => {
      state.isChangedAuthType = null;
    })

    // Установить статус сравнения введенного пароля с актуальным паролем
    .addCase(checkPassword.fulfilled.type, (state, action: PayloadAction<PasswordCheckDto>) => {
      state.isCorrectPassword = action.payload.isCorrect;
    })

    .addCase(checkPassword.rejected.type, (state, action: PayloadAction<PasswordCheckDto>) => {
      state.isCorrectPassword = action.payload.isCorrect;
    })

    // Сбросить статус сравнения введенного пароля с актуальным паролем
    .addCase(clearPasswordCorrectStatus, (state) => {
      state.isCorrectPassword = null;
    });
});
